use cortex_m::itm;
use cortex_m::peripheral::ITM;
use embassy::util::Forever;
use log::{LevelFilter, Metadata, Record};

static LOGGER: Forever<Logger> = Forever::new();
pub struct Logger {
    itm: ITM,
}
unsafe impl Send for Logger {}
unsafe impl Sync for Logger {}
impl Logger {
    pub fn start(itm: ITM, filter: LevelFilter) {
        let logger = LOGGER.put(Logger { itm });

        if let Ok(_) = log::set_logger(logger) {
            log::set_max_level(filter);
        };
    }
}
impl log::Log for Logger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= log::max_level()
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let target = if !record.target().is_empty() {
                record.target()
            } else {
                record.module_path().unwrap_or_default()
            };
            itm::write_fmt(
                unsafe { &mut *(&self.itm.stim[0] as *const _ as *mut _) },
                format_args!("{} [{}] {}\r\n", record.level(), target, record.args()),
            );
        }
    }

    fn flush(&self) {}
}

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
    log::error!("{}", info);
    loop {}
}
